<?php

/**
 * 云仓商城商品查询服务接口中心
 */

namespace App\Service\OrderService\OrderQueryService;

use App\Service\AppService\MyDate;
use App\Service\BaseService;
use App\Service\Code\Normal;
use App\Model\PssModel\Template;
use App\Model\PssModel\GoodsCart;
use App\Model\PssModel\ShopSeckill;
use App\Model\PssModel\ShopSeckillUserGoods;
use App\Service\SearchService\Index\ShopCommodityIndex;
use App\Model\CommodityModel\Classifyinfo;
use App\Model\CommodityModel\Brandinfo;
use App\Model\CommodityModel\CommodityArchives;
use App\Service\CommodityService\BbcBestGoodsService;

class QueryGoodsMicService extends BaseService
{
    //列表分页限制
    const PAGE_LIMIT = 25;
    //百分率基数
    const BASE_PRICE_RATE       = 1.00;
    //小数点位数
    const BASE_SCALE_TYPE       = 4;
    //金额计算精度
    const BASE_FLOAT            = 2;
    
    //下单redis
    const RDB_ORDER_GOODS_NUM   = 5;
    const REDIS_KEY_GOODS       = 'user_place_order_';
    const expire                = 60*60;
    
    /**
     * 获取微服务商品搜索列表数据接口
     * @param array $param
     */
    public function getShopIndexGoodsPageList( $param = [] ) 
    {
        $body   = $param['body'];
        $binfo  = $param['binfo'];
        $page   = $body['page'] ?? 0;
        $page   = $page > 0 ? ($page -1) : $page;
        $limit  = isset($body['limit']) ? $body['limit'] : self::PAGE_LIMIT ;
        //获取商品微服务接口数据
        $res = $this->getSearchGoodsListByMicroServiceParameters($param);
        if( $res['code'] != Normal::SUC ) {
            return $res;
        }

        //处理分页数据
        $pageInfo  = $res['data'];
        $res = $this->getGoodsListByCaculationAction($binfo,$pageInfo['data'],$body['order_goods'] ?? [] );
        if( $res['code'] != Normal::SUC ) {
            return $res;
        }
        $pageInfo['data'] = $res['data'];
        return Normal::returnCode(Normal::SUC,"OK",$pageInfo);
    }
    
    /**
     * 获取当前优选数据
     * @param array $param
     */
    public function getShopBestGoodsList( $param = [] )
    {
        $body   = $param['body'];
        $binfo  = $param['binfo'];
        $CopWhere = [
            'bid'       => 0,
            'skuids'    => $body['skuIDS']
        ];
        $res = BbcBestGoodsService::instance()->getDispatchGoodsList($CopWhere);
        if( empty($res['data']) ) {
            return $res;
        }
        return $this->getGoodsListByCaculationAction($binfo,$res['data'],$body['order_goods'] ?? [] );
    }
    
    /**
     * 获取商品微服务搜索列表数据
     * @param array $param
     */
    public function getSearchGoodsListByMicroServiceParameters( $param = [] )
    {
        $body   = $param['body'];
        $binfo  = $param['binfo'];
        $page   = isset($body['page']) && $body['page'] >= 0 ? $body['page'] : 1;
        $page   = $page > 0 ? ($page -1) : $page;
        $limit  = isset($body['limit']) ? $body['limit'] : 15;
        $search  = ShopCommodityIndex::instance()->search($page,$limit,$body);
        $dataList = [];
        if( !empty($search['hits']['hits']) ) {
            foreach ($search['hits']['hits'] as $item )
            {
                $dataList[] = $item['_source'];
                unset($item);
            }
        }
        
        $SkuIDs = array_column($dataList,'SkuID');
        //从ES出来之后，开始查询商品
        $CopWhere = [
            'bid'       => 0,
            'page'      => $page,
            'limit'     => $limit ,
            'skuids'    => $SkuIDs,
            'order'     => [
                'price' => $body['sort']['price'] ?? 'asc',
            ]
        ];
        $res = BbcBestGoodsService::instance()->getDispatchGoodsList($CopWhere);
        $pageData = array_column($res['data'],null,'SkuID');
		$listPage = [];
        foreach ($dataList as & $item ) 
        {
            //es里面的数据可能下架了
            if( isset($pageData[$item['SkuID']]) ) 
            {
				$tempData = $pageData[$item['SkuID']];
				$tempData['HasTaxCostPrice'] = $item['HasTaxCostPrice'];
				$listPage[] = $tempData;
            }
			unset($item);
        }
		
		$total = $search['hits']['total']['value'];
		$countpage = ceil($total/$limit);
		$pageInfo = [
			'current_page'	=> $page,
			'last_page'		=> $countpage,
			'per_page'		=> $limit,
			'total'			=> $total,
			'data'			=> $listPage
		];
		return Normal::returnCode(Normal::SUC,"获取成功",$pageInfo);
    }
    
    /**
     * 查询品牌和分类
     * @param array $param
     */
    public function getSearchClassAndBrands( $param = [] )
    {
        $body   = $param['body'];
        $result = ShopCommodityIndex::instance()->getSearchClassAndBrands($body);
        if( empty($result['aggregations']) ) {
            return Normal::returnCode(Normal::SUC,"搜索数据为空",$result);
        }
        
        $aggregations   = $result['aggregations'];
        $t_class_ids    = array_column($aggregations['t_class_id']['buckets'],'key');
        $brand_ids      = array_column($aggregations['brand_id']['buckets'],'key');
        $goods_types    = array_column($aggregations['goods_type']['buckets'],'key');
        $classList      = [];
        if( !empty($t_class_ids) ) {
            $classifyInfos = Classifyinfo::instance()->getClassByBids($t_class_ids);
            foreach ($classifyInfos as $item ) {
                $classList[] = [
                    'class_id'      => $item['id'],
                    'class_name'    => $item['class_name'],
                    'class_image'   => $item['Image'] ? $item['Image'] :'',
                ];
                unset($item);
            }
        }
        $brandList = [];
        if( !empty($brand_ids) ) 
        {
            $brandInfos = Brandinfo::instance()->getBrandListsByIds($brand_ids);
            foreach ($brandInfos as $item ) {
                $brandList[] = [
                    'brand_id'      => $item['brand_id'],
                    'brand_name'    => $item['brand_name'],
                    'brand_image'   => $item['Image'] ? $item['Image'] :'',
                ];
                unset($item);
            }
        }
        
        $commodifyTypeList = [];
        if( !empty($goods_types) )
        {
            foreach ($goods_types as $goods_type ) {
                $commodifyTypeList[] = [
                    'goods_type'        => $goods_type,
                    'goods_type_name'   => CommodityArchives::instance()->goods_types[$goods_type]??'未定义',
                ];
            }
        }
        return Normal::returnCode(Normal::SUC,"获取成功",[
            'brandList' => $brandList,
            'classList' => $classList,
            'commodifyTypeList' => $commodifyTypeList
        ]);
    }
    
    /**
     * 获取计算后的商品列表数据清单
     * @param array $binfo 商户信息
     * @param array $goodsList 原始商品信息
     * @param array $order_goods 购物车商品信息
     * @param array $isSecSkillGoods(是否秒杀列表)
     * @return mixed
     */
    public function getGoodsListByCaculationAction( array $binfo = [] , array $goodsList = [] ,array $order_goods = [] ,$sec_id = false )
    {
        //获取价格模板数据
        $res = $this->getUserTemplateInfo($binfo);
        if( $res['code'] != Normal::SUC ) {
            return $res;
        }
        
        //根据模板计算会员价格
        $tplInfo   = $res['data'];
        $goodsList = $this->priceTpl([
            'tplInfo'           => $tplInfo,
            'goodsList'         => $goodsList,
            'binfo'             => $binfo,
            'sec_id'            => $sec_id,
            'order_goods'       => $order_goods
        ]);        
        return Normal::returnCode(Normal::SUC,"OK",$goodsList);
    }
    
    /**
     * 获取用户模板详情
     * @param array $binfo
     */
    public function getUserTemplateInfo( $binfo = [] )
    {
        //如果没有登录，获取默认模板价格
        if( isset($binfo['user_level']) && $binfo['user_level'] > 0 ) {
            $template_info = Template::instance()->getTemplateInfoByUserLevel($binfo['user_level']);
        } else {
            $template_info = Template::instance()->getTemplateInfoById();
        }
        
        if( empty($template_info) ) {
            return Normal::returnCode(Normal::FAIL,"未配置价格模板");
        }
        
        $tpl_contents = @json_decode($template_info['tpl_contents'],true);
        if( !isset($tpl_contents['price_settlement_rate']) || 
            !isset($tpl_contents['price_rate']) || 
            !isset($tpl_contents['price_market_rate']) ) {
           return Normal::returnCode(Normal::FAIL,"获取价格模板异常，请联系管理员处理"); 
        }
        
        return Normal::returnCode(Normal::SUC,"OK",$template_info);
    }
    
    /**
     * 根据模板类型计算价格数据
     * 1、默认模板价格
     * 2、价格利润率
     * 3、价格利润金额
     * 4、分类利润率
     * @param array $tplInfo
     * @param array $goodsList
     * @return mixed
     */
    public function priceTpl( $param = [] )
    {
        $tplInfo            = $param['tplInfo'];
        $goodsList          = $param['goodsList'];
        $binfo              = $param['binfo'];
        $order_goods        = $param['order_goods']??[];
        $sec_id             = $param['sec_id']??false;
        $tpl_contents       = @json_decode($tplInfo['tpl_contents'],true);
        
        //获取秒杀商品信息,如果是秒杀活动则需要获取一次原始商品信息
        $skuIds             = array_column($goodsList,'SkuID');
        if( $sec_id ) {
            $CopWhere = [
                'bid'       => 0,
                'skuids'    => $skuIds
            ];
            $res = BbcBestGoodsService::instance()->getDispatchGoodsList($CopWhere);
            if( $res['code'] != Normal::SUC ) {
                return $res;
            }
            $goodsList = $res['data'];
        }

        
        //通过SKUIDS集合，获取活动价格
        $secSkillInfo       = ShopSeckill::instance()->querySecSkillGoodsInfoBySkuIds($skuIds,$sec_id);
        
        //判断活动是否开始
        $seckillStatus = false;
        if( !empty($secSkillInfo['seckill_info']) ) {
            $seckillStatus = ShopSeckill::instance()->getSeckillGoodsActivity($secSkillInfo['seckill_info']);
        }
        
        //活动商品组
        $secSkillGoods = $secSkillInfo['secGoodsList']??[];
        //处理正常商品价格问题
        foreach ($goodsList as & $skuInfo )
        {
            //获取SKU信息
            $goods_id = $skuInfo['SkuID'];
            //是否正价购买
            $isCanBuySecSkillGoods  = true;
            
            //判断是否开启限购
            if( !empty($secSkillInfo['seckill_info']) ) 
            {
                $seckill_info       = $secSkillInfo['seckill_info'];
                $buy_limit_number   = $seckill_info['buy_limit_number'];
                $seckill_id         = $seckill_info['id'];
                //活动已开始的话，要判断用户满足限购条件
                if( $seckillStatus ) {
                    $orderGroupGoodsList = [];
                    foreach ($order_goods as $item ) {
                        if( isset($orderGroupGoodsList[$item['goods_id']]) ) {
                            $orderGroupGoodsList[$item['goods_id']] += $item['goods_num'];
                        } else {
                            $orderGroupGoodsList[$item['goods_id']] = $item['goods_num'];
                        }
                    }
                    
                    //判断单个商品是否超出限购
                    if( isset($orderGroupGoodsList[$goods_id]) && $buy_limit_number > 0 && $orderGroupGoodsList[$goods_id] > $buy_limit_number ) {
                        $isCanBuySecSkillGoods = false;
                    } else {
                        //判断限购且登录的情况下，去判断是否已经购买过
                        if( isset($orderGroupGoodsList[$goods_id]) && isset($binfo['bid']) ) {
                            $isCanBuySecSkillGoods = ShopSeckillUserGoods::instance()->queryUserSecSkillGoodsBuy($binfo['bid'],$seckill_id,$goods_id,$orderGroupGoodsList[$goods_id]);
                        }
                    }
                }
            }
            
            $SpecListInfo = $this->getGoodsSpecList($skuInfo,$tplInfo,$secSkillGoods[$goods_id]??[],$seckillStatus,$seckill_info??[],$isCanBuySecSkillGoods);
            $skuInfo['SpecList'] = $SpecListInfo['SpecList'];
            $skuInfo = $this->getGoodsSkuInfo($skuInfo,$tplInfo);
        }
        return $goodsList;
    }
    
    /**
     * skuinfo
     * @param array $skuInfo
     */
    public function getGoodsSkuInfo( $skuInfo = [], $tplInfo = [] )
    {
        //当前价格模板
        $tpl_contents = @json_decode($tplInfo['tpl_contents'],true);
        
        //处理图片
        $Images         = @json_decode($skuInfo['Images'],true);
        $images         = $this->getResetImagesList($Images);
        //商品类型
        $commodity_type = $skuInfo['CommodityType'];
        $goodsTypeName  = CommodityArchives::instance()->goods_types[$commodity_type]?? '未定义';
        $commodity_customer_info = [
            'payDeclare'                    => $skuInfo['PayDeclare'],
            'payDeclareEnumDescription'     => $skuInfo['PayDeclare'] == 1 ? '需要支付单申报' : '',
            'orderDeclare'                  => $skuInfo['OrderDeclare'],
            'orderDeclareEnumDescription'   => $skuInfo['OrderDeclare'] == 1 ? '需要订单申报' : '',
            'enterpriseName'                => $skuInfo['EnterpriseName'],
            'enterpriseCode'                => $skuInfo['EnterpriseCode'],
            'declareSKUCode'                => $skuInfo['DeclareSKUCode'],
            'declareCommodityName'          => $skuInfo['DeclareCommodityName'],
            'function'                      => $skuInfo['DeclareSKUCode'],
            'declareBarCode'                => $skuInfo['DeclareBarCode'],
            'customMeasurementUnitCode'     => $skuInfo['DeclareMeasurementUnitCode'],
            'customMeasurementUnit'         => $skuInfo['DeclareMeasurementUnit'],
            'customCountryCode'             => $skuInfo['DeclareCountryCode'],
            'customCountry'                 => $skuInfo['DeclareCountry'],
            'customCurrencyCode'            => $skuInfo['DeclareCurrencyCode'],
            'customCurrency'                => $skuInfo['DeclareCurrency'],
            'customSpecifications'          => $skuInfo['DeclareSpecifications'],
        ];
        
        //处理spu属性贵格问题
        $spuSpecJsonBody = @json_decode($skuInfo['SpuSpecJsonBody'],true);
        //处理规格库存问题
        $batch = [
            'supplier_skuid'    => $skuInfo['SupplierCommodityID'],
            'supplier_skucode'  => $skuInfo['SKUCode'],
            'defaultStock'      => $skuInfo['DefaultStock'],
            'num'               => $skuInfo['Number'],
            'batch_no'          => $skuInfo['BatchNo'],
            'batch_id'          => $skuInfo['BatchID'],
            'status'            => 1,
            'spec_list'         => $skuInfo['SpecList']
        ];
        $goods_batch_list = [$batch];
        $store = [
            "linkSkuID"                     => $skuInfo['SkuID'],
            "store_customer_name"           => $skuInfo['PayDeclare'] == 1 ? $skuInfo['WarehouseName'] : '优选仓',
            "store_type"                    => $skuInfo['WarehouseType'],
            "storeDisplayName"              => $skuInfo['PayDeclare'] == 1 ? $skuInfo['WarehouseName'] : '优选仓',
            "store_id"                      => $skuInfo['WarehouseID'],
            "store_code"                    => $skuInfo['WarehouseCode'],
            "store_name"                    => $skuInfo['WarehouseName'],
            "store_account"                 => $skuInfo['WarehouseAccount'],
            "store_isCombineOrders"         => $skuInfo['IsCombineOrders'],
            "store_mode"                    => $skuInfo['OrderDockMode'],
            "supplier_skuid"                => $skuInfo['SupplierCommodityID'],
            "supplier_skucode"              => $skuInfo['SupplierCommoditySkuCode'],
            "supplier_id"                   => $skuInfo['SupplierID'],
            "supplier_alias"                => $skuInfo['SupplierAlias'],
            "supplier_code"                 => $skuInfo['SupplierCode'],
            "supplier_companystatus"        => $skuInfo['CompanyStatus'],
            "supplier_commoditydockmode"    => $skuInfo['OrderDockMode'],
            "supplier_stockdockmode"        => 0,
            "supplier_orderdockmode"        => 0,
            "goods_batch_list"              => $goods_batch_list
        ];
        $storeList = [$store];
        
        //获取当前仓库信息
        $stockInfo      = current($storeList);
        $goodsBatch     = current($stockInfo['goods_batch_list']);
        $spec_list      = $goodsBatch['spec_list'];
        $firstSpec      = current($spec_list);
        $mainImageUrl   = $skuInfo['Images'];
        
        //零售价比例
        $price_settlement_rate = bcadd((string)'100',(string)$tpl_contents['price_settlement_rate']??0.00,2);
        $price_settlement_rate = bcdiv((string)$price_settlement_rate,'100',4);
        
        //判断是否有秒杀价格
        if( isset($firstSpec['is_seckill']) && $firstSpec['is_seckill'] == 1 ) {
            $show_price = $firstSpec['price'];
        } else {
            $HasTaxCostPrice = $skuInfo['HasTaxCostPrice'] ?? 0.00;
            $HasTaxCostPrice = $HasTaxCostPrice ? $HasTaxCostPrice : $firstSpec['price'];
            $show_price = bcmul((string)$price_settlement_rate, (string)$HasTaxCostPrice,2);
        }
        
        return [
            'Abbreviation'          => $skuInfo['Name'],
            'Description'           => $skuInfo['Description'],
            'brand_name'            => $skuInfo['BrandName'],
            'goods_name'            => $skuInfo['Name'],
            'goods_type'            => $skuInfo['CommodityType'],
            'goods_type_name'       => $goodsTypeName,
            'image'                 => $images,
            'barcode'               => $skuInfo['BarCode'],
            'skucode'               => $skuInfo['SKUCode'],
            'tax'                   => $skuInfo['TaxRate'] ? $skuInfo['TaxRate'] : '0.000',
            'weight'                => $skuInfo['Weight'],
            'goods_id'              => $skuInfo['SkuID'],
            'price'                 => $firstSpec['price'],
            'show_price'            => number_format((float)$show_price,2),//商品列表、首页推荐商品、商品详情、商品组列表展示的价格、秒杀商品列表
            'is_seckill'            => $firstSpec['is_seckill'] ?? 0,
            'store_id'              => $skuInfo['WarehouseID'],
            'storeList'             => $storeList,
            'is_combine'            => $skuInfo['IsCombineOrders'] ? true : false ,//是否合并支付下单的仓库
            'is_check_idcard'       => isset($skuInfo['IsNeedIDCard']) && $skuInfo['IsNeedIDCard'] ? 1 : 0,//是否需要强制身份证（1-需要，0-不需要）
            'supplier_id'           => $skuInfo['SupplierID'],
            'freight_template_id'   => $skuInfo['FreightTemplateID'] ? $skuInfo['FreightTemplateID'] : 1,//模板ID
            'is_free_postfee'       => isset($skuInfo['IsFreeShipping']) && $skuInfo['IsFreeShipping'] == 1 ? 1 : 0,//是否包邮
        ];
    }
    
    /**
     * 处理图片
     * 区分主图 为第一张
     * @param array $images
     */
    public function getResetImagesList( $images = [] )
    {
        if( empty($images) ) {
            return [];
        }
        $temp = [];
        $isMainUrls = [];
        $otherUrls = [];
        foreach ($images as $item )
        {
            if( $item['IsMain'] == 1 && empty($isMainUrls) ) {
                $isMainUrls[] = $item['ImageUrl'];
            } else {
                $otherUrls[] = $item['ImageUrl'];
            }
        }
    
        return array_merge($isMainUrls,$otherUrls);
    }
    
    /**
     * 处理规格结构
     * @param array $skuInfo
     * @param array $tplInfo
     * @param array $secSkillGoods
     * @param string $seckillStatus
     * @param string $isCanBuySecSkillGoods
     */
    public function getGoodsSpecList( $skuInfo = [] ,$tplInfo = [],$secSkillGoods= [],$seckillStatus = false , $seckill_info = [] ,$isCanBuySecSkillGoods = true )
    {
        $specList = @json_decode($skuInfo['SpecList'],true);
        $newSpecList = [];
        $goods_id = $skuInfo['SkuID'];
        foreach ($specList as $item )
        {
            $specificationNum   = (int)$item['SpecNum'];
//            $specificationPrice = (float)$item['SpecPrice'];
            $specificationPrice = (float)($item['SpecFreightPrice']??$item['SpecPrice']);
            $marketPrice        = $skuInfo['MarketPrice'];//市场单价
            $singleSpecPrice    = bcdiv((string)$specificationPrice, (string)$specificationNum,2);
            $spec = [
                "spec_num"    	=> $specificationNum,
                "specName"    	=> "{$specificationNum}{$skuInfo['UnitName']}",
                "expired_date"	=> MyDate::getDateByMysqlDateFields($skuInfo['CalibrationPeriodTime']),
                "make_date"   	=> '',
                "price"       	=> $specificationPrice,
                "priceCost"   	=> (float)$specificationPrice,
                'singlePrice' 	=> bcmul((string)$singleSpecPrice, '100'),
                'priceCostPost' => bcsub($specificationPrice,$item['SpecPrice'],2)
            ];
            //计算当前价格
            $calc_spec = $this->calcPriceByTemplate($tplInfo,array_merge($spec,[
                'has_rate'  => $skuInfo['IsHaveTaxRate'],
                'tax_rate'  => $skuInfo['TaxRate']
            ]));
            
            $tpl_type   = $tplInfo['tpl_type'];
            $user_type  = $tplInfo['user_type'];
            $user_level = $tplInfo['user_level'];
            $store_id   = $skuInfo['WarehouseID'];
            $batch_no   = $skuInfo['BatchNo'];
            $spec_num   = $spec['spec_num'];
            
            //如果存在秒杀价格
            if( !empty($secSkillGoods) &&
                isset($secSkillGoods['spec_list'][$store_id]) &&
                isset($secSkillGoods['spec_list'][$store_id]['goods_batch_list'][$batch_no]) &&
                isset($secSkillGoods['spec_list'][$store_id]['goods_batch_list'][$batch_no]['spec_list'][$spec_num])
                && $isCanBuySecSkillGoods
                && $seckillStatus//存在秒杀开始或者未开始的情况
                )
            {
                $calc_spec['price']         = $secSkillGoods['spec_list'][$store_id]['goods_batch_list'][$batch_no]['spec_list'][$spec_num]['seckill_price'];
                //计算秒杀详情
                //计算日期
                $now                        = time();
                //当日0点
                $now_date                   = date("Ymd");
                //当日0点时间戳
                $now_start_time             = strtotime($now_date);
                //当日实时开始已用秒数
                $now_date_mics              = $now - $now_start_time;
                $calc_spec['seckill_info']  = json_encode($seckill_info,JSON_UNESCAPED_UNICODE);
                $calc_spec['cut_time']      = $seckill_info['sale_end_time'] - $now_date_mics;
                $calc_spec['is_seckill']    = 1;
                //会员用户和下游渠道商户 直接用结算价单价展示批发价
            } else if ( ($user_level > 0 && $user_type == 1) || ( $user_type == 2 && $tpl_type > 1 )  ) {
                $calc_spec['price'] = $calc_spec['priceSettlement'];
                $calc_spec['is_seckill']    = 0;
            } else {//否则用建议零售价单价展示批发价
                $calc_spec['price'] = $calc_spec['priceSettlement'];
                //$calc_spec['priceSettlement'] = $calc_spec['price'];
                $calc_spec['is_seckill']    = 0;
            }
            $spec = array_merge($spec,$calc_spec);
            $newSpecList[] = $spec;
        }
        
        //寻找最大值和最小值
        $singlePrices  = array_column($newSpecList, 'singlePrice');
        $minPrice      = min($singlePrices);
        $isMinStockSpecificationItem = false;
        foreach ($newSpecList as & $item )
        {
            if( $item['singlePrice'] == $minPrice && $isMinStockSpecificationItem == false ) {
                $item['isMinStockSpecificationItem'] = true;
            } else {
                $item['isMinStockSpecificationItem'] = false;
            }
            unset($item['singlePrice']);
        }
    
        return [
            'minSinglePrice'    => $minPrice,
            'maxSinglePrice'    => max($singlePrices),
            'SpecList'          => $newSpecList
        ];
    }
    
    /**
     * 根据不同价格模板计算价格
     * @param array $price_contents
     * @param array $data
     */
    public function calcPriceByTemplate( $price_contents = [] , $data = [] )
    {
        $tpl_contents = @json_decode($price_contents['tpl_contents'],true);
        $spec_price   = $data['price'];//商品成本规格价格
        //如果是不含税价格 
        if( $data['has_rate'] != 1 ) {
            $tax_rate   = bcadd((string)$data['tax_rate'],(string)1,4);
            $spec_price = bcmul((string)$spec_price,(string)$tax_rate,2);
        }
        return [
            'price'             => bcmul($spec_price, bcadd(self::BASE_PRICE_RATE,bcdiv($tpl_contents['price_rate'], 100,self::BASE_SCALE_TYPE),self::BASE_SCALE_TYPE),self::BASE_FLOAT),
            'priceSettlement'   => bcmul($spec_price, bcadd(self::BASE_PRICE_RATE,bcdiv($tpl_contents['price_settlement_rate'], 100,self::BASE_SCALE_TYPE),self::BASE_SCALE_TYPE),self::BASE_FLOAT),
            'priceMarket'       => bcmul($spec_price, bcadd(self::BASE_PRICE_RATE,bcdiv($tpl_contents['price_market_rate'], 100,self::BASE_SCALE_TYPE),self::BASE_SCALE_TYPE),self::BASE_FLOAT),
        ];
    }
    
    /**
     * 获取商城商品数据详情
     * @param array $param
     */
    public function getShopGoodsDetail( $param = [] )
    {
        $binfo = $param['binfo'];
        $body  = $param['body'];
        if( empty($body['goods_id']) ) {
            return Normal::returnCode(Normal::FAIL,"缺失商品id");
        }
        
        //根据商品goods_id 获取商品实时价格并且参与计算
        $goods_id = checkFields($body['goods_id']);
        $queryParameters = [
            'body' => [
                'skuIDS' => [(string)$goods_id],
                'limit'  => 1
            ],
            'binfo' => $binfo,
        ];
        //获取商品微服务接口数据
        $res = $this->getShopBestGoodsList($queryParameters);
        if( $res['code'] != Normal::SUC  || empty($res['data'])) {
            return $res;
        }
        $goodsList = $res['data'];
        //获取库存信息
        $detail           = current($goodsList);
        $storeList        = $detail['storeList'];
        $currentStockInfo = current($storeList);
        $batch_list       = $currentStockInfo['goods_batch_list'];
        $currentBatchInfo = current($batch_list);
        
        //获取库存
        $detail['num'] = $currentBatchInfo['num'];
        $detail['batch_list'][] = $detail['storeList'];
        $detail['price'] = number_format($detail['price'],2);
        unset($detail['storeList']);
        
        return Normal::returnCode(Normal::SUC,"OK",$detail);
    }
    
    /**
     * 计算商品价格
     * @param array $param
     */
    public function getGoodsPrice( $param = [] ) 
    {
        $body   = $param['body'];
        $binfo  = $param['binfo'];
        if( empty($body['goods_list']) ) {
            return Normal::returnCode(Normal::FAIL,'except goods_list');
        }
        
        $res = $this->checkGoodsOrderBatch($param);
        if($res['code'] != Normal::SUC ) {
            return $res;
        }
        
        $orderGoods = $res['data']['orderGoods'];
        $specInfo = current($orderGoods);
        $goodsMoney = bcmul($specInfo['goods_num'], $specInfo['price'],2);
        return Normal::returnCode(Normal::SUC,"获取成功",[
            'goodsMoney' => number_format($goodsMoney,2)
        ]);
    }
    
    /**
     * 立即购买接口
     * @param array $param
     */
    public function placeOrder( $param = [] )
    {
        if( empty($param['body']['goods_list']) ) {
            return Normal::returnCode(Normal::FAIL,"goods_list 不能为空");
        }
        
        if( !is_array($param['body']['goods_list']) ) {
            return Normal::returnCode(Normal::FAIL,"goods_list必须为数据对象");
        }
        
        if( count($param['body']['goods_list']) > 1 && ! $this->checkIsAllowedCustomsDeclarationSplit($param['body']['pay_way']) ) {
            return Normal::returnCode(Normal::FAIL,"不支持多个商品进行结算下单");
        }
        
        return $this->checkBuyGoods($param);
    }
    
    /**
     * 检查是否满足
     * @param 支付单报关拆单 $pay_way
     * @return true - 代表允许多商品合并支付结算下单，否则只能单商品下单
     */
    public function checkIsAllowedCustomsDeclarationSplit( $pay_way )
    {
        $declaration = json_decode(CUSTOMS_DECLARATION_SPLIT,true);
        return in_array($pay_way, $declaration) ? 1 : 0 ;
    }
    
    /**
     * 检查需要购买下单的商品
     * @param array $param
     */
    public function checkBuyGoods( $param = [] )
    {
        $body   = $param['body'];
        $binfo  = $param['binfo'];
        if( empty($body['orderType']) ) {
            return Normal::returnCode(Normal::FAIL,'except orderType');
        }
    
        if( empty($body['goods_list']) ) {
            return Normal::returnCode(Normal::FAIL,'except goods_list');
        }
        
        //校验提交商品的参数
        $result = $this->checkOrderGoods($body);
        if($result['code'] != Normal::SUC ) {
            return $result;
        }
        
        $res = $this->checkGoodsOrderBatch($param);
        if($res['code'] != Normal::SUC ) {
            return $res;
        }
        
        //下单商品
        $goodsInfo  = $res['data']['goodsInfo'];
        $orderItem  = $res['data']['orderGoods'];
        $orderType  = $body['orderType'];
        $redis_cache_data = [
            'account'       => $binfo['account'],
            'orderType'     => $orderType,
            'goodsInfo'     => $goodsInfo,
            'orderGoods'    => $orderItem,
            'order_time'    => time(),
        ];
        $str = json_encode($redis_cache_data,JSON_UNESCAPED_UNICODE);
        $redis_cache_key = md5($str);
        $redis = BaseService::instance()->getRedisObj();
        $redis->select(self::RDB_ORDER_GOODS_NUM);
        $redis->setex(self::REDIS_KEY_GOODS.$redis_cache_key,self::expire,$str);
        return Normal::returnCode(Normal::SUC,"操作成功",[
            'orderKey'  => $redis_cache_key,
            'orderType' => $orderType,
            'orderItem' => $orderItem,
            'goodsInfo' => $goodsInfo
        ]);
    }
        
    /**
     * 获取校验商品真实信息
     * @param array $param
     */
    public function checkGoodsOrderBatch( $param = [] ) 
    {
        $binfo = $param['binfo'];
        $body  = $param['body'];
        $goodsIds = array_unique(array_column($body['goods_list'],'goods_id'));
        $goodsIds = array_values($goodsIds);
        
        //根据商品goods_id 获取商品实时价格并且参与计算
        $queryParameters = [
            'body' => [
                'skuIDS'        => $goodsIds,
                'order_goods'   => $body['goods_list']??[],
            ],
            'binfo' => $binfo,
        ];
        
        $res = $this->getShopBestGoodsList($queryParameters);
        if( $res['code'] != Normal::SUC ) {
            return $res;
        }
        
        //最优解商品
        $goodsList = $res['data'];
        $existedGoods = array_column($goodsList, 'goods_id');
        $diff = array_diff($goodsIds, $existedGoods);
        if( !empty($diff) ) {
            $str = implode(",", $diff);
            return Normal::returnCode(Normal::FAIL,"商品ID{$str}暂无库存或已下架");
        }
        $data = [
            'goodsInfo'         => $goodsList,
            'orderGoods'        => $body['goods_list'],
            'binfo'             => $binfo
        ];
        return Normal::returnCode(Normal::SUC,"OK",$data);
    }
    
    /**
     * 校验商品组
     * @param array $goods_list
     */
    public function checkOrderGoods( $param )
    {
        $goods_list = $param['goods_list'];
        foreach ($goods_list as $item )
        {
            if( isset($param['orderType']) && $param['orderType'] == 2 && empty($item['cart_id'])  ) {
                return Normal::returnCode(Normal::FAIL,"购物车下单需要cart_id");
            }
            
            if( empty($item['goods_id']) ) {
                return Normal::returnCode(Normal::FAIL,"except param goods_list.goods_id");
            }
            
            if( empty($item['spec_num']) ) {
                return Normal::returnCode(Normal::FAIL,"except param goods_list.spec_num");
            }
            
            if( empty($item['goods_num']) ) {
                return Normal::returnCode(Normal::FAIL,"except param goods_list.goods_num");
            }
    
            if( empty($item['store_id']) ) {
                return Normal::returnCode(Normal::FAIL,"except param goods_list.store_id");
            }
    
            if( empty($item['batch_no']) ) {
                return Normal::returnCode(Normal::FAIL,"except param goods_list.batch_no");
            }
        }
        return Normal::returnCode(Normal::SUC,"OK",$goods_list);
    }
    
    /**
     * 加入购物车接口
     * @param array $param
     */
    public function addGoodsCart( $param = [] ) 
    {
        $body   = $param['body'];
        $binfo  = $param['binfo'];
        $param  = [
            'body' => ['goods_list' => [$body]],
            'binfo' => $binfo,
        ];
        //校验提交商品的参数
        $res = $this->checkOrderGoods($param['body']);
        if($res['code'] != Normal::SUC ) {
            return $res;
        }
        
        //获取真实商品
        $res = $this->checkGoodsOrderBatch($param);
        if($res['code'] != Normal::SUC ) {
            return $res;
        }
        
        $param['body']['goodsInfo'] = $res['data']['goodsInfo'];
        return GoodsCart::instance()->addCart($param);
    }
}
